/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package interp;

import java.util.ArrayList;

/**
 *
 * @author Mikael Köhlmyr | mikael@kohlmyr.com | http://www.kmyr.net
 */
public class Interpreter {
    private String[] actions = {"clear", "incr", "decr", "while"};
    private String[] keywords = {"not", "do", "end"};
    private ArrayList<String> vars = new ArrayList<String>();
    private ArrayList<Integer> vals = new ArrayList<Integer>();
    private ArrayList<String> code = new ArrayList<String>();
    private int current;
        public Interpreter(ArrayList<String> code){
            this.code = code;
            runRoot(this.code);
        }

        public void runRoot(ArrayList<String> code){
            for(current = 0; current < code.size(); current++){
                String c = code.get(current);
                //System.out.println(c);
                if(contains(actions, c)){
                    performAction(current, c);
                }
            }
        }

        private void performAction(int index, String method){
            if(method.equals("clear")){
                String var;
                if(isVar(var = code.get(index + 1))){
                    if(vars.contains(var)){
                        vals.set(vars.indexOf(var), 0);
                        System.out.println("Reset var: " + var + " via clear");
                    }
                    else{
                        vars.add(var);
                        vals.add(0);
                        System.out.println("Found new variable from clear: " + var);
                    }
                }
            }
            else if(method.equals("incr")){
                String var;
                if(isVar(var = code.get(index + 1))){
                    alterVar(var, 1);
                    System.out.println("Incremented variable: " + var + " to have value " + vals.get(vars.indexOf(var)));
                }
            }
            else if(method.equals("decr")){
                String var;
                if(isVar(var = code.get(index + 1))){
                    alterVar(var, -1);
                    System.out.println("Decremented variable: " + var + " to have value " + vals.get(vars.indexOf(var)));
                }
            }
            else if(method.equals("while")){ 
                
                // obviously will not work with nested loops. fuck.
                // If we search for the next end that isnt preceeded by a while we can use that

                String var;
                Integer condition;
                int end = -1;
                if(isVar(var = code.get(index + 1)) && code.get(index + 2).equals("not") && (condition = recastVal(code.get(index + 3))) != null && code.get(index + 4).equals("do")){
                    ArrayList<String> loop = new ArrayList<String>();
                    for(int i = index + 5; i < code.size(); i++){
                        if(code.get(i).equals("end")){
                            end = i;
                            break;
                        }
                        loop.add(code.get(i));
                        i++;
                    }
                    if(end != -1){
                        if(!loop.isEmpty()){
                            while(vals.get(vars.indexOf(var)) != condition){
                                System.out.println("loop");
                                runRoot(loop);
                            }
                            System.out.println("ended loop");
                            current = end;
                        }
                    }
                    else{
                        System.out.println("Found a while loop with no ending");
                    }
                    
                }
            }
            else{
                System.out.println("Error evaluating keyword: " + code.get(index));
            }
        }

        private void alterVar(String var, int modifier){
            int i = vars.indexOf(var);
            vals.set(i, vals.get(i) + modifier);
        }

        private boolean isVar(String input){
            if(!isVal(input)){
                if(contains(keywords, input) || contains(actions, input)){//shortest search placed first
                    return false;
                }
                return true;
            }
            return false;
        }

        private boolean contains(String[] collection, String object){
            for(String s : collection){
                if(object.equals(s)){
                    return true;
                }
            }
            return false;
        }

        private boolean isVal(String input){
            if(recastVal(input) != null){
                return true;
            }
            else{
                return false;
            }
        }

        private Integer recastVal(String val){
            try{
                int value = Integer.valueOf(val).intValue();
                return value;
            }
            catch(NumberFormatException e){
                return null;
            }
        }
}
